package com.ldoublem.loadingviewlib.view;

import com.ldoublem.loadingviewlib.view.base.LVBase;
import ohos.agp.animation.Animator;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * Created by lumingmin on 16/6/29.
 */

public class LVGhost extends LVBase implements Component.DrawTask {

    float mWidth = 0f;
    float mHight = 0f;
    Paint mPaint, mPaintHand, mPaintShadow;
    RectFloat rectFGhost = new RectFloat();
    RectFloat rectFGhostShadow = new RectFloat();
    float mPadding;
    int mskirtH = 0;
    float wspace = 10f;
    float hspace = 10f;
    private float mAnimatedValue = 0f;
    int onAnimationRepeatFlag = 1;
    Path path = new Path();

    public LVGhost(Context context) {
        this(context, null);
    }

    public LVGhost(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public LVGhost(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        mPadding = 10;
    }

    @Override
    protected void InitPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_STYLE);
        mPaint.setColor(Color.WHITE);
        mPaintHand = new Paint();
        mPaintHand.setAntiAlias(true);
        mPaintHand.setStyle(Paint.Style.FILL_STYLE);
        mPaintHand.setColor(new Color(Color.argb(220, 0, 0, 0)));
        mPaintShadow = new Paint();
        mPaintShadow.setAntiAlias(true);
        mPaintShadow.setStyle(Paint.Style.FILL_STYLE);
        mPaintShadow.setColor(new Color(Color.argb(60, 0, 0, 0)));
        addDrawTask(this);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        mWidth = getWidth();
        mHight = getHeight();
        mskirtH = (int) (mWidth / 40);
        float distance = (mWidth - 2 * mPadding) / 3 * 2 * mAnimatedValue;
        rectFGhost.left = mPadding + distance;
        rectFGhost.right = (mWidth - 2 * mPadding) / 3 + distance;
        float moveY;
        float moveYMax = mHight / 4f / 2f;
        float shadowHighMax = 5f;
        float shadowHigh = 0f;
        if (mAnimatedValue <= 0.25) {
            moveY = (float) (moveYMax / 0.25 * mAnimatedValue);
            rectFGhost.top = moveY;
            rectFGhost.bottom = mHight / 4 * 3 + moveY;
            shadowHigh = shadowHighMax / 0.25f * mAnimatedValue;
        } else if (mAnimatedValue > 0.25 && mAnimatedValue <= 0.5f) {
            moveY = (float) (moveYMax / 0.25 * (mAnimatedValue - 0.25f));
            rectFGhost.top = moveYMax - moveY;
            rectFGhost.bottom = mHight / 4 * 3 + moveYMax - moveY;
            shadowHigh = shadowHighMax - shadowHighMax / 0.25f * (mAnimatedValue - 0.25f);
        } else if (mAnimatedValue > 0.5 && mAnimatedValue <= 0.75f) {
            moveY = (float) (moveYMax / 0.25 * (mAnimatedValue - 0.5f));
            rectFGhost.top = moveY;
            rectFGhost.bottom = mHight / 4 * 3 + moveY;
            shadowHigh = shadowHighMax / 0.25f * (mAnimatedValue - 0.5f);
        } else if (mAnimatedValue > 0.75 && mAnimatedValue <= 1f) {
            moveY = (float) (moveYMax / 0.25 * (mAnimatedValue - 0.75f));
            rectFGhost.top = moveYMax - moveY;
            rectFGhost.bottom = mHight / 4 * 3 + moveYMax - moveY;
            shadowHigh = shadowHighMax - shadowHighMax / 0.25f * (mAnimatedValue - 0.75f);
        }
        rectFGhostShadow.top = mHight - 25 + shadowHigh;
        rectFGhostShadow.bottom = mHight - 5 - shadowHigh;
        rectFGhostShadow.left = rectFGhost.left + 5 + shadowHigh * 3;
        rectFGhostShadow.right = rectFGhost.right - 5 - shadowHigh * 3;
        drawShadow(canvas);
        drawHead(canvas);
        drawBody(canvas);
        drawHand(canvas);
    }

    private void drawShadow(Canvas canvas) {
        canvas.drawArc(rectFGhostShadow, new Arc(0, 360, false), mPaintShadow);
    }

    private void drawHead(Canvas canvas) {
        canvas.drawCircle(rectFGhost.left + rectFGhost.getWidth() / 2,
                rectFGhost.getWidth() / 2 + rectFGhost.top,
                rectFGhost.getWidth() / 2 - 15,
                mPaint
        );
    }

    private void drawBody(Canvas canvas) {
        path.reset();
        float x = (float) ((rectFGhost.getWidth() / 2 - 15) * Math.cos(5 * Math.PI / 180f));
        float y = (float) ((rectFGhost.getWidth() / 2 - 15) * Math.sin(5 * Math.PI / 180f));
        float x2 = (float) ((rectFGhost.getWidth() / 2 - 15) * Math.cos(175 * Math.PI / 180f));
        float y2 = (float) ((rectFGhost.getWidth() / 2 - 15) * Math.sin(175 * Math.PI / 180f));
        path.moveTo(rectFGhost.left + rectFGhost.getWidth() / 2 - x, rectFGhost.getWidth() / 2 - y + rectFGhost.top);
        path.lineTo(rectFGhost.left + rectFGhost.getWidth() / 2 - x2, rectFGhost.getWidth() / 2 - y2 + rectFGhost.top);
        path.quadTo(rectFGhost.right + wspace / 2, rectFGhost.bottom,
                rectFGhost.right - wspace, rectFGhost.bottom - hspace);
        float a = mskirtH;
        float m = (rectFGhost.getWidth() - 2 * wspace) / 7f;
        for (int i = 0; i < 7; i++) {
            if (i % 2 == 0) {
                path.quadTo(rectFGhost.right - wspace - m * i - (m / 2), rectFGhost.bottom - hspace - a,
                        rectFGhost.right - wspace - (m * (i + 1)), rectFGhost.bottom - hspace);
            } else {
                path.quadTo(rectFGhost.right - wspace - m * i - (m / 2), rectFGhost.bottom - hspace + a,
                        rectFGhost.right - wspace - (m * (i + 1)), rectFGhost.bottom - hspace);
            }
        }
        path.quadTo(rectFGhost.left - 5, rectFGhost.bottom,
                rectFGhost.left + rectFGhost.getWidth() / 2 - x, rectFGhost.getWidth() / 2 - y + rectFGhost.top);
        path.close();
        canvas.drawPath(path, mPaint);
    }

    private void drawHand(Canvas canvas) {
        canvas.drawCircle(rectFGhost.left + rectFGhost.getWidth() / 2 - mskirtH * 3 / 2 + mskirtH * onAnimationRepeatFlag,
                rectFGhost.getWidth() / 2 + mskirtH + rectFGhost.top,
                mskirtH * 0.9f, mPaintHand
        );
        canvas.drawCircle(rectFGhost.left + rectFGhost.getWidth() / 2 + mskirtH * 3 / 2 + mskirtH * onAnimationRepeatFlag,
                rectFGhost.getWidth() / 2 + mskirtH + rectFGhost.top,
                mskirtH * 0.9f, mPaintHand
        );
    }

    public void setViewColor(int color) {
        mPaint.setColor(new Color(color));
        invalidate();
    }

    public void setHandColor(int color) {
        mPaintHand.setColor(new Color(color));
        invalidate();
    }

    @Override
    protected void OnAnimationRepeat(Animator animation) {
        onAnimationRepeatFlag = onAnimationRepeatFlag * -1;
        if (onAnimationRepeatFlag == -1) {
            wspace = 22;
        } else {
            wspace = -2;
        }
    }

    @Override
    protected void OnAnimationUpdate(float value) {
        mAnimatedValue = value;
        invalidate();
    }

    @Override
    protected int OnStopAnim() {
        mAnimatedValue = 0f;
        wspace = 10;
        onAnimationRepeatFlag = 1;
        invalidate();
        return 1;
    }

    @Override
    protected int SetAnimRepeatMode() {
        return REVERSE;
    }

    @Override
    protected void AinmIsRunning() {
        wspace = -2;
    }

    @Override
    protected int SetAnimRepeatCount() {
        return Integer.MAX_VALUE;
    }

}
